﻿
#include "strid.h"
#include "AppUI.h"

//////////////////////////////////////////////////////////////////////////
//以下为操作控件和资源的便利性封装
ImageRType GetIconType(int ResId)
{
	//资源类型的设计很有问题
	//好在大多数资源都是IT_Bitmap，判断一下就能处理
	if (ResId>=RID_太初_馥郁的欢愉 && ResId<=RID_太初_辨明异徒的食指)
		return IT_Animation;
	if (ResId==RID_Q奶妈 || ResId==RID_Q剑帝)
		return IT_Animation;
	return IT_Bitmap;
}

ImageR_t* EasyLoadImageR(int ResId,ImageRType Type/*=IT_Bitmap*/)
{
	if (Type==IT_Bitmap)
		return ResMgr->LoadImageR(GetResId(ResId));
	else if (Type==IT_Scale9)
		return ResMgr->LoadScale9R(GetResId(ResId));
	else if (Type==IT_Animation)
		return ResMgr->LoadAnimationR(GetResId(ResId));
	return NULL;
}

//先设置位置信息，再设置本体信息
int ControlNextX=0;
int ControlNextY=0;
int ControlPageId=0;
UIControl* ControlParent;

void SetCreateControlParam(int X,int Y,UIControl* Parent,int PageId)
{
	ControlNextX=X;
	ControlNextY=Y;
	ControlParent=Parent;
	ControlPageId=PageId;
}

CButton* EasyCreateButton(int CtrlId,int Width,int Height,WCHAR* Text)
{
	CButton* CtrlButton=new CButton(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height,Text,FALSE);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlButton);
	return CtrlButton;
}

CButton* EasyCreateFlatButton(int CtrlId,int Width,int Height,WCHAR* Text)
{
	CButton* CtrlButton=new CButton(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height,Text,TRUE);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlButton);
	return CtrlButton;
}

CImage* EasyCreateImage(int CtrlId,int Width,int Height,int ResId/*=-1*/,ImageRType Type/*=IT_Bitmap*/)
{
	CImage* CtrlImage=new CImage(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height);
	if (ResId!=-1)
	{
		ImageR_t* ImgRes=EasyLoadImageR(ResId,Type);
		CtrlImage->SetImage(ImgRes);
	}
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlImage);
	return CtrlImage;
}

CLabel* EasyCreateLabel(int CtrlId,int Width,int Height,WCHAR* Text)
{
	CLabel* CtrlLabel=new CLabel(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height,Text);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlLabel);
	return CtrlLabel;
}

CLineLabel* EasyCreateLineLabel(int CtrlId,int Width,int Height,WCHAR* Text)
{
	CLineLabel* CtrlLabel=new CLineLabel(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height,Text);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlLabel);
	return CtrlLabel;
}

CCheckBox* EasyCreateCheckBox(int CtrlId,WCHAR* Text)
{
	CCheckBox* CtrlCheckBox=new CCheckBox(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Text);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlCheckBox);
	return CtrlCheckBox;
}

CVScrollView* EasyCreateScrollView(int CtrlId,int Width,int Height,int VirtualHeight)
{
	CVScrollView* CtrlScrollView=new CVScrollView(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height);
	CtrlScrollView->SetVirtualHeight(VirtualHeight);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlScrollView);
	return CtrlScrollView;
}

CEdit* EasyCreateEdit(int CtrlId,int Width)
{
	CEdit* CtrlEdit=new CEdit(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlEdit);
	return CtrlEdit;
}

CSpListBox* EasyCreateSpListBox(int CtrlId,int Width,int Height)
{
	CSpListBox* CtrlSpListBox=new CSpListBox(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlSpListBox);
	return CtrlSpListBox;
}

CDropList* EasyCreateDropList(int CtrlId,int Width,BOOL IconStyle)
{
	CDropList* CtrlDropList=new CDropList(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,IconStyle);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlDropList);
	return CtrlDropList;
}

CHSlider* EasyCreateSlider(int CtrlId,int Width)
{
	CHSlider* CtrlSlider=new CHSlider(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlSlider);
	return CtrlSlider;
}

CHTabView* EasyCreateTabView(int CtrlId,int Width,int Height)
{
	CHTabView* CtrlTabView=new CHTabView(GetCtrlId(CtrlId),ControlNextX,ControlNextY,Width,Height);
	UiMgr->InsertControl(ControlPageId,ControlParent,CtrlTabView);
	return CtrlTabView;
}


float EditChangeAdjust(CEdit* CtrlEdit,WCHAR* Text,int Len,int RoundNum,BOOL Positive)
{
	WCHAR Buf[20];
	for (int i=0;i<Len;i++)
	{
		//ParseFloatText()会跳过无法解析的字符
		if (Text[i]=='%')
			Text[i]='x';
	}
	float Value=ParseFloatText(Text,Len);
	if (Positive && Value<0.0f)
		Value*=-1.0f;
	if (RoundNum<0)
	{
		//整数型的向下取整
		Value=floor(Value);
		swprintf(Buf,L"%d",(int)Value);
		CtrlEdit->SetText(Buf);
	}
	else
	{
		if (RoundNum>9)
			RoundNum=9;
		//百分比型的保留至多9位小数
		Value=fround(Value,RoundNum);
		//生成0-9的格式化字符串
		WCHAR FmtStr[5]={'%','.','0','f',0};
		FmtStr[2]+=RoundNum;
		swprintf(Buf,FmtStr,Value);
		CtrlEdit->SetText(Buf);
	}
	return Value;
}


//////////////////////////////////////////////////////////////////////////
//以下为装备描述相关代码，装备描述和自定义词条描述还没处理完
std::vector<装备描述_t*> 装备描述文本;
std::vector<装备词条描述_t*> 装备词条描述文本;

BOOL 加载装备描述(WCHAR* FileName)
{
	HANDLE hFile=CreateFile(FileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if (hFile==INVALID_HANDLE_VALUE)
		return FALSE;
	DWORD FileSize=GetFileSize(hFile,NULL);
	if (FileSize<100)
	{
		CloseHandle(hFile);
		return FALSE;
	}
	WCHAR* DescText=new WCHAR[FileSize/2];
	ReadFile(hFile,DescText,FileSize,&FileSize,NULL);
	CloseHandle(hFile);

	auto GetTag=[](WCHAR* Name)->int
	{
		if (wcscmp(Name,L"装备描述_普通装备.txt")==0)
			return 普通装备描述;
		else if (wcscmp(Name,L"装备描述_贴膜装备.txt")==0)
			return 贴膜装备描述;
		return -1;
	};
	int Tag=GetTag(FileName);

	enum _State
	{
		SReady,
		SName,
		SDesc,
	} State=SReady;

	//跳过BOM
	int Cur=1;
	int Len=FileSize/2;
	int Pos=Cur;
	装备描述_t* 装备描述项=NULL;
	while (Cur<Len)
	{
		if (State==SReady)
		{
			装备描述项=new 装备描述_t;
			装备描述项->Name=NULL;
			装备描述项->Desc=NULL;
			装备描述项->Tag=-1;
			if (DescText[Cur]=='\r' && DescText[Cur+1]=='\n')
				Cur+=2;
			if (DescText[Cur]=='@')
				Cur++;
			Pos=Cur;
			State=SName;
			continue;
		}
		WCHAR ch=DescText[Cur];
		if (State==SName)
		{
			if (ch=='@')
			{
				//@@作为结束
				delete 装备描述项;
				break;
			}
			else if (ch=='\r')
			{
				DescText[Cur]=0;
				装备描述项->Name=wstrdup(DescText+Pos);
				装备描述项->Tag=Tag;
				Pos=Cur+2;
				Cur++;	//跳过\n
				State=SDesc;
			}
		}
		else if (State==SDesc)
		{
			if (ch=='\r')
			{
				if (DescText[Cur+1]=='\n' && DescText[Cur+2]=='@')
				{
					//特别要求两件装备的描述间空一行，描述以上个\r\n结尾（含上个\r\n）
					DescText[Cur]=0;
					装备描述项->Desc=wstrdup(DescText+Pos);
					DescText[Cur]='\r';
					装备描述文本.push_back(装备描述项);
					State=SReady;	//SReady里负责跳过\r\n@序列
					continue;
				}
			}
		}
		Cur++;
	}
	delete[] DescText;

	return TRUE;
}

BOOL 加载装备词条描述(WCHAR* FileName)
{
	HANDLE hFile=CreateFile(FileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if (hFile==INVALID_HANDLE_VALUE)
		return FALSE;
	DWORD FileSize=GetFileSize(hFile,NULL);
	if (FileSize<100)
	{
		CloseHandle(hFile);
		return FALSE;
	}
	WCHAR* DescText=new WCHAR[FileSize/2];
	ReadFile(hFile,DescText,FileSize,&FileSize,NULL);
	CloseHandle(hFile);

	auto GetTag=[](WCHAR* Name)->int
	{
		int Len=wcslen(Name);
		if (Len>6 && memcmp(Name,L"武器贴膜词条",6*sizeof(WCHAR))==0)
			return 武器贴膜词条描述_普通;
		if (Len>8 && memcmp(Name,L"武器贴膜龙焰词条",8*sizeof(WCHAR))==0)
			return 武器贴膜词条描述_龙焰;
		if (Len>6 && memcmp(Name,L"传说贴膜词条",6*sizeof(WCHAR))==0)
			return 传说贴膜词条描述;
		//todo：后面会补全所有部位，按部位分类
		if (Len>4 && memcmp(Name,L"武器词条",4*sizeof(WCHAR))==0)
			return 自定义词条描述;
		return -1;
	};

	enum _State
	{
		SReady,
		SName,
		SDesc,
	} State=SReady;

	//跳过BOM
	int Cur=1;
	int Len=FileSize/2;
	int Pos=Cur;
	装备词条描述_t* 装备描述项=NULL;
	while (Cur<Len)
	{
		if (State==SReady)
		{
			装备描述项=new 装备词条描述_t;
			装备描述项->Name=NULL;
			装备描述项->Num=0;
			memset(装备描述项->Desc,0,10*sizeof(int));
			装备描述项->Tag=-1;
			if (DescText[Cur]=='\r' && DescText[Cur+1]=='\n')
				Cur+=2;
			if (DescText[Cur]=='@')
				Cur++;
			Pos=Cur;
			State=SName;
			continue;
		}
		WCHAR ch=DescText[Cur];
		if (State==SName)
		{
			if (ch=='@')
			{
				//@@作为结束
				delete 装备描述项;
				break;
			}
			else if (ch=='\r')
			{
				DescText[Cur]=0;
				装备描述项->Name=wstrdup(DescText+Pos);
				装备描述项->Tag=GetTag(装备描述项->Name);
				Pos=Cur+2;
				Cur++;	//跳过\n
				State=SDesc;
			}
		}
		else if (State==SDesc)
		{
			if (ch=='\r')
			{
				if (DescText[Cur+1]=='\n' && DescText[Cur+2]=='@')
				{
					//特别要求两件装备的描述间空一行
					//遇到此序列一定无描述，直接到下个装备
					装备词条描述文本.push_back(装备描述项);
					State=SReady;	//SReady里负责跳过\r\n@序列
					continue;
				}
				else
				{
					//不含每行的\r\n
					DescText[Cur]=0;
					装备描述项->Desc[装备描述项->Num]=wstrdup(DescText+Pos);
					装备描述项->Num++;
					Pos=Cur+2;
					Cur++;
				}
			}
		}
		Cur++;
	}
	delete[] DescText;
	return TRUE;
}

void 加载所有装备描述()
{
	加载装备词条描述(L"Save\\词条描述_传说贴膜.txt");
	加载装备词条描述(L"Save\\词条描述_武器贴膜.txt");
	加载装备词条描述(L"Save\\词条描述_自定义.txt");
	//加载装备描述(L"Save\\装备描述_普通装备.txt");
	//加载装备描述(L"Save\\装备描述_贴膜装备.txt");
}

void 清理所有装备描述()
{
	std::vector<装备描述_t*>::iterator it1;
	
	for (it1=装备描述文本.begin();it1!=装备描述文本.end();it1++)
	{
		装备描述_t* 装备描述=*it1;
		delete[] 装备描述->Name;
		delete[] 装备描述->Desc;
		delete 装备描述;
	}
	装备描述文本.clear();

	std::vector<装备词条描述_t*>::iterator it2;
	for (it2=装备词条描述文本.begin();it2!=装备词条描述文本.end();it2++)
	{
		装备词条描述_t* 装备词条描述文本=*it2;
		delete[] 装备词条描述文本->Name;
		for (int i=0;i<装备词条描述文本->Num;i++)
			delete[] 装备词条描述文本->Desc[i];
		delete 装备词条描述文本;
	}
	装备词条描述文本.clear();
}


//////////////////////////////////////////////////////////////////////////
//以下为伤害结果相关代码，负责计算模块到UI的对接，由计算模块修改，目前使用随机数进行测试
void 伤害计算结果_t::Init()
{
	//随机数据仅用作测试
	for (int i=0;i<属性结果总数;i++)
	{
		属性结果[i]=(float)(rand()%1000-500);
		if (rand()%2==0)
			属性结果[i]=属性结果[i]*0.1f;
	}
	总伤害=rand()%10*1000000000000.0+rand()%10000*100000000.0+rand()%10000*10000.0+rand()%10000;

	技能结果数=rand()%10+11;
	for (int i=0;i<技能结果数;i++)
	{
		技能结果[i].技能图标Id=RID_技能图标_奶妈+i;	//主动18个图标，后面2个借用被动的
		技能结果[i].技能等级=10;
		技能结果[i].技能次数=3;
		技能结果[i].技能冷却时间=20.7f;
		技能结果[i].技能平均伤害=10000000000;
		技能结果[i].技能总伤害=30000000000;
		技能结果[i].技能占比=rand()%1000*0.001f;
	}

	技能冷却结果数=rand()%10+11;
	for (int i=0;i<技能冷却结果数;i++)
	{
		技能冷却结果[i].技能图标Id=RID_技能图标_奶妈+i;
		技能冷却结果[i].技能原始时间=100.0f;
		技能冷却结果[i].技能当前时间=rand()%50;
		技能冷却结果[i].技能缩减率=技能冷却结果[i].技能当前时间/技能冷却结果[i].技能原始时间;
		技能冷却结果[i].技能无色数=16;
	}

	被动技能数=rand()%5+6;
	for (int i=0;i<被动技能数;i++)
	{
		被动技能结果[i].技能图标Id=RID_被动技能图标_奶妈+i;
		被动技能结果[i].技能等级=rand()%100;
	}

	for (int i=0;i<全部装备部位总数;i++)
	{
		装备结果[i].打造物攻加成=rand()%1000+1000;
		装备结果[i].打造魔攻加成=rand()%1000+1000;
		装备结果[i].打造独立加成=rand()%1000+1000;
		装备结果[i].打造四维加成=rand()%100+100;
		装备结果[i].锻造独立加成=rand()%100+800;
		装备结果[i].满足条件=rand()%2;
		wcscpy(装备结果[i].条件描述,(装备结果[i].满足条件)?L"满足条件":L"不满足条件");
	}

	系统奶=rand()%15000+10000;

	Valid=FALSE;
}

void 伤害计算结果_t::Uninit()
{

}

void 伤害计算结果_t::SetBase()
{
	总伤害对照=总伤害;

	技能结果对照数=技能结果数;
	for (int i=0;i<技能结果数;i++)
		技能结果对照[i]=技能结果[i];
	for (int i=技能结果数;i<20;i++)
	{
		技能结果对照[i].技能图标Id=-1;
		技能结果对照[i].技能平均伤害=0;
		技能结果对照[i].技能总伤害=0;
	}

	技能冷却结果对照数=技能冷却结果数;
	for (int i=0;i<技能冷却结果数;i++)
		技能冷却结果对照[i]=技能冷却结果[i];
	for (int i=技能冷却结果数;i<20;i++)
	{
		技能冷却结果对照[i].技能图标Id=-1;
		技能冷却结果对照[i].技能当前时间=0;
	}
	
	Valid=TRUE;
}

void 伤害计算结果_t::Sort()
{
	//新结果的技能数量可能变更
	//排序之后，还要让旧结果和新结果的位置一一对应
	//旧结果里不存在的技能，其相关字段已设置为0，不会造成负面影响
	InsertSort(技能结果,技能结果数);
	for (int i=0;i<技能结果数;i++)
	{
		for (int j=0;j<技能结果对照数;j++)
		{
			//以图标ID查找对应技能，交换至位置一致（类似冒泡排序）
			if (技能结果对照[j].技能图标Id==技能结果[i].技能图标Id)
			{
				技能结果_t Temp=技能结果对照[j];
				技能结果对照[j]=技能结果对照[i];
				技能结果对照[i]=Temp;
			}
		}
	}
	
	InsertSort(技能冷却结果,技能冷却结果数);
	for (int i=0;i<技能冷却结果数;i++)
	{
		for (int j=0;j<技能冷却结果对照数;j++)
		{
			//以图标ID查找对应技能，交换至位置一致（类似冒泡排序）
			if (技能冷却结果对照[j].技能图标Id==技能冷却结果[i].技能图标Id)
			{
				技能冷却结果_t Temp=技能冷却结果对照[j];
				技能冷却结果对照[j]=技能冷却结果对照[i];
				技能冷却结果对照[i]=Temp;
			}
		}
	}
}

伤害计算结果_t 伤害计算结果;


